T H E Medium Access Control (MAC) LAYER ======================================== (C) 1993 by Oliver Rehmann 100016.732@compuserve.com Motivation ========== When I first came into contact with the MAC layer I was a high school student. It was a dream of mine to write the worlds best network sniffer. :-) The project failed because of the MAC layer. There was no accurate information about this layer of the OSI reference model and as a high school student I did not have enough money to buy all those expensive books about networks. Another stumbling block was that I didn't have a low level driver for my LAN adapter (NE2000). I know there exist hundreds of books about this subject. What I am trying to convey you is a summary of information you need when working on the MAC layer of an Ethernet. Thus the information provided in this document is only for Ethernet !!! History of ETHERNET =================== Ethernet was developed by Xerox in the seventies. The specification of Ethernet Version 1.0 has been released 1980 by Dec, Intel and Xerox (The Blue Book Ethernet). Two years later the same group (DIX) released version 2.0 of Ethernet. Another three years later the IEEE group specified the 802.3 paper. Quick Reference : Ethernet (Version 1.0) ---------------------------------------- Topology : Bus Media Access : CSMA/CD = Carrier Sense Multiple Access with Collision Detection Throughput : 10 Mbit/sec. max. distance between two stations : 2800m max. stations : 1024 Frame format: ------------- Preamble length : 8 Bytes Destination address : 6 Bytes Source address : 6 Bytes Type field : 2 Bytes Data field length : 46 - 1500 Bytes Frame Checksum : 4 Bytes ------------------------ 72 - 1526 Bytes ======================== The OSI Reference model ======================= When talking about networks, it is useful to refer to the OSI reference model (OSI = Open Systems Interconnection). ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Layer 7 ³ ³ Application ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Layer 6 ³ ³ Presentation ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Layer 5 ³ ³ Session ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Layer 4 ³ ³ Transport ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³ Layer 3 ³ ³ Network ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä ³ Layer 2b ³ ³ Logical Link Control ³ D a t a L i n k C o n t r o l ³ (LLC) ³ Ã Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä´ L a y e r ³ Layer 2a ³ ³ Medium Access Control ³ (2a + 2b) ³ (MAC) ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä ³ Layer 1b ³ ³ Physical (PHY) ³ P h y s i c a l ³ ³ Ã Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä´ L a y e r ³ Layer 1a ³ ³ Physical Medium ³ (1a + 1b) ³ Dependent (PMD) ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä Ä What I will describe are layers 2a and 2b (MAC and LLC). Normally, if you are interfacing with your LAN adapter at packet level, layer one is invisible to you. The transceiver is on this layer. Layer 2 ------- Data Link Control: Errorfree Frame Transmission between physically connected nodes. On this layer the programmer has to handle incoming and outgoing packets. These packets often are called frames. IEEE 802.3 (Ethernet) Frame =========================== ÚÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄ¿ ³ 7 Bytes ³ 1 Byte ³ 6 Bytes ³ 6 Bytes ³ 2 Bytes ³ 46...1500 Bytes ³ 4 Bytes ³ ³ Preamble ³ SFD ³ Dest. ³ Source ³ Length ³ of Data ³ FCS ³ ³ ³ ³ Address ³ Address ³ (Type) ³ (at least 46 B) ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÙ ³ LLC ³ legend of frame format: Preamble : 7 Bytes => 10101010 SFD : 1 Byte Start Frame Delemiter => 10101011 Preamble and SFD are used for synchronisation of all receivers. Destination address : 6 Byte hardware address of receiver Source address : 6 Byte hardware address of sender Ä example. 80Ä00Ä20Ä7FÄ59ÄE8 => 8000207F59E8 This is called an Ethernet hardware address. They are unique. Length : If this word (2 Bytes) is smaller than 5EEh (1500+18) the frame is a standard IEEE 802.3 frame. Length represents the number of bytes in the Data (LLC) field. If the length field is greater than 5EEh it is an ETHERNET frame. The difference is that length is no longer a valid length but it represents a type. (See table in file ETHERNET.TYP) Data : 46..1500 Bytes of Data. The smallest frame on an Ethernet (LLC) (CSMA/CD) has to be at least 64 Bytes. The header consists of 18 Bytes so the data field must hold 46 or more Bytes. FCS : Frame Check Sequence. This is a cyclic redundancy checksum Data representation ------------------- When receiving packets from your LAN adapter (ex. through Crynrware packet drivers) you must know what type of CPU your computer has. This is important for data representation. The type (length) field in an Ethernet frame always corresponds to a Big Endian system (ex. Motorola 68000, etc.). Intel 80x86 CPUs are Little Endian systems so you have to swap the lo and hi byte of a word. Ex. DOD IP = 0800h -> Swap -> 0008h (on a 80x86 PC) Summary ------- Ethernet and IEEE 802.3 frames differ from each other by the type field. Ethernet defines different types (see file ETHERNET.TYP). IEEE 802.3 uses the type field as a length field to say how many bytes the data field holds. The type of the packet is stored in the LLC header which is part of the data field. This can be very time consuming work for a LAN adapter because it always has to look into the LLC header to determine the packet type. Ethernet addresses ------------------ The first three bytes of an Ethernet address identify the vendor of the LAN adapter. example: 08-00-09-12-7F-05 : 08-00-09 -> Vendor is Hewlett Packard (HP) 08-00-20-24-AB-55 : 08-00-20 -> Vendor is Sun Microsystems (SUN) The well known vendor identifiers are listed in the file ETHERNET.VND. Turbo Pascal definitions ------------------------ Data structures used for MAC layer handling. TYPE { 6 Byte Ethernet address } EthernetAddr = Array[00..05] of Byte; { Definition of a Medium Access Control header } MACHeader = RECORD DestAddr : EthernetAddr; SourceAddr : EthernetAddr; TypeLen : Word; END; Turbo Pascal functions ---------------------- Functions for handling data on the MAC layer. FUNCTION SwapWord(sWord : Word) : Word; {ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º FUNCTION SwapWord; º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Description : ³ Swaps the lo and hi byte of a word. º º ³ Used for type (length) field manipulation. º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Creation date : ³ 20-SEPT-93 º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ} VAR tWord : Word; BEGIN tWord := (Lo(sWord) SHL 8) + Hi(sWord); SwapWord := tWord; END; FUNCTION ByteToHEXASCII(tByte : Byte) : String; {ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º FUNCTION ByteToHEXASCII (...) : String; º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Description : ³ Converts a byte into a HEX-ASCII-String. º º ³ º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Creation date : ³ 20-SEPT-93 º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ} CONST HEXChars: array [0..15] of char = '0123456789ABCDEF'; VAR Nibble1 : Byte; Nibble2 : Byte; tStr : String; BEGIN Nibble1 := (tByte AND $0F); { AND 00001111b } Nibble2 := (tByte AND $F0) SHR 4; { AND 11110000b } tStr := HEXChars[Nibble2]+HEXChars[Nibble1]; ByteToHEXASCII := tStr; END; FUNCTION WordToHEXASCII(tWord : Word) : String; {ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º FUNCTION WordToHEXASCII (...) : String; º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Description : ³ Converts a word into a HEX-ASCII-String º º ³ º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Creation date : ³ 20-SEPT-93 º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ} VAR tStr : String; BEGIN tStr := ByteToHexASCII(Hi(tWord)); tStr := tStr+ByteToHexASCII(Lo(tWord)); WordToHexASCII := tStr; END; PROCEDURE TranslateEthernetAddress(tStr : String; VAR tEtheraddr : EthernetAddr); {ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º PROCEDURE TranslateEthernetAddress(..); º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Description : ³ Translates a dash separated Ethernet address into º º ³ 6 Bytes. º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Creation date : ³ 20-SEPT-93 º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ} VAR tDigit : String; tByte : Byte; Err : Integer; tVal : Byte; BEGIN tDigit :=''; FOR tByte := 1 TO Length(tStr) DO BEGIN IF (Copy(tStr,tByte,1) <> '-') THEN tDigit := tDigit + Copy(tStr,tByte,1); END; FOR tByte := 0 TO 5 DO BEGIN Val('$'+Copy(tDigit,(tByte*2)+1,2),tVal,Err); tEtheraddr[tByte] := tVal; END; END; FUNCTION GetEthernetAddress(tEtherAddr : EthernetAddr) : String; {ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º FUNCTION GetEthernetAddress; º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Description : ³ Translates an Ethernet address into a dash º º ³ separated string. º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Creation date : ³ 20-SEPT-93 º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ} VAR tString : String; tDigit : String[02]; tCount : Byte; AddrLen : Byte; BEGIN AddrLen := SizeOf(EthernetAddr)-1; tString := ''; FOR tCount := 0 TO AddrLen DO BEGIN tString := tString + ByteToHexASCII(tEtherAddr[tCount]); IF (tCount < AddrLen) THEN tString := tString + '-'; END; GetEthernetAddress := tString; END; FUNCTION CompareEthernetAddr(Addr1,Addr2 : EthernetAddr) : Boolean; {ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º FUNCTION CompareEthernetAddr; º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Description : ³ Compares two Ethernet addresses. º º ³ Returns TRUE if they are equal. º ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ º Creation date : ³ 20-SEPT-93 º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ} VAR Result : Boolean; Count : Byte; BEGIN Result := TRUE; Count := 0; REPEAT IF (Addr1[Count] <> Addr2[Count]) THEN Result := FALSE; Inc(Count); UNTIL Not(Result) OR (Count = 6); CompareEthernetAddr := Result; END; Conditions ========== This paper can be freely copied as long as Copyright indications are not changed or dropped. The author can not be held responsible for any damages resulting from the use of information given in this document. The author can be reached through the following e-mail adresses: Internet : 100016.732@compuserve.com CZ8OR@zcvx00.decnet.ascom.ch CompuServe: ID : 100016,732